Repository Public
1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2// /contact/[category] — le formulaire d'une porte d'entrée du centre de3// communication. Rendu serveur : le registre fournit les champs, la session4// KA ID (si présente) préremplit l'identité — on ne redemande pas ce qu'on5// sait déjà, et la demande est liée au compte côté serveur.6import type { Metadata } from "next";7import { notFound } from "next/navigation";8import { getSessionUser } from "@/lib/auth";9import { findUserById, parseSocials } from "@/lib/db";10import { categoryBySlug } from "@/lib/comms/categories";11import { CategoryIcon } from "../icons";12import ContactForm from "../ContactForm";1314// Page dynamique : la session KA ID (cookies) préremplit le formulaire.15export const dynamic = "force-dynamic";1617export async function generateMetadata({18 params,19}: {20 params: Promise<{ category: string }>;21}): Promise<Metadata> {22 const cat = categoryBySlug((await params).category);23 if (!cat) return {};24 return {25 title: `${cat.title} — nous joindre`,26 description: cat.intro,27 };28}2930/* Contenus éditoriaux propres à certaines catégories */3132function InvestisseursIntro() {33 const PROFILES = [34 "Investisseurs privés",35 "Fonds (VC, PE)",36 "Family offices",37 "Investisseurs stratégiques",38 "Partenaires financiers",39 "Collaborations & acquisitions",40 ];41 return (42 <div className="mt-8 grid gap-8 lg:grid-cols-[1.4fr_1fr]">43 <div>44 <p className="text-[14.5px] leading-relaxed text-ink-2">45 Le Groupe KA construit et opère{" "}46 <strong className="text-ink">quatorze plateformes d'agrégation</strong>{" "}47 entièrement automatisées sur sa propre infrastructure — et publie ses48 chiffres comme ses données : en entier. Aucune ronde de financement49 n'est en cours, mais nous sommes ouverts aux discussions50 sérieuses : investissement, partenariat financier, acquisition, joint51 venture ou simple introduction.52 </p>53 <p className="mt-4 text-[14.5px] leading-relaxed text-ink-2">54 Commencez par les{" "}55 <a href="/investisseurs" className="font-bold text-green underline underline-offset-4">56 documents corporatifs en libre accès57 </a>{" "}58 (plan d'affaires, prévisions 2026–2029, infrastructure, coûts59 mesurés), puis présentez-vous ci-dessous. Ces demandes sont traitées60 confidentiellement par les relations investisseurs.61 </p>62 </div>63 <ul className="rule-ink grid grid-cols-1 gap-y-2 self-start pt-4">64 {PROFILES.map((p) => (65 <li key={p} className="gk-mono flex items-center gap-3 text-[11.5px] font-bold tracking-[0.06em] uppercase">66 <span className="h-[6px] w-[6px] flex-none rotate-45 bg-green" aria-hidden="true" />67 {p}68 </li>69 ))}70 </ul>71 </div>72 );73}7475function CarrieresIntro() {76 return (77 <div className="mt-8 max-w-3xl">78 <p className="text-[14.5px] leading-relaxed text-ink-2">79 <strong className="text-ink">Carrières chez Groupe KA</strong> — nous80 construisons des agrégateurs automatisés, une infrastructure de calcul81 maison et des outils d'IA appliquée, depuis le Québec. Deux façons82 de postuler : répondre à un poste précis, ou nous faire une{" "}83 <strong className="text-ink">candidature spontanée</strong> — « je ne84 vois pas de poste correspondant, mais je veux travailler avec Groupe85 KA ». Les deux sont enregistrées et lues avec la même attention.86 </p>87 <p className="gk-mono mt-4 text-[11px] leading-relaxed text-ink-3">88 Les offres publiées par les employeurs du Québec sont sur{" "}89 <a href="https://www.job-ka.com" target="_blank" rel="noopener noreferrer" className="underline underline-offset-2">90 Job·Ka91 </a>{" "}92 — ce formulaire-ci concerne les emplois chez Groupe KA même. Votre CV93 est conservé de façon sécurisée et n'est jamais partagé.94 </p>95 </div>96 );97}9899function SecuriteIntro() {100 return (101 <div className="mt-8 max-w-3xl rounded-xl border-[1.5px] border-ink bg-lime-soft p-5">102 <p className="text-[13.5px] leading-relaxed text-ink-2">103 <strong className="text-ink">Divulgation responsable :</strong> si vous104 avez trouvé une vulnérabilité, décrivez-la ici sans l'exploiter105 au-delà du nécessaire. Le signalement peut être{" "}106 <strong className="text-ink">anonyme</strong> — ne laissez un courriel107 que si vous souhaitez un suivi. Les signalements critiques passent108 automatiquement en priorité urgente.109 </p>110 </div>111 );112}113114export default async function ContactCategoryPage({115 params,116}: {117 params: Promise<{ category: string }>;118}) {119 const cat = categoryBySlug((await params).category);120 if (!cat) notFound();121122 // Préremplissage KA ID (serveur) — jamais confiance au client pour le lien123 // user_id/ka_id : /api/contact relit la session lui-même.124 const user = await getSessionUser();125 const defaults: Record<string, string> = {};126 if (user) {127 const row = findUserById(user.id);128 const [first, ...rest] = (user.name ?? "").trim().split(/\s+/);129 if (first) defaults.first_name = first;130 if (rest.length) defaults.last_name = rest.join(" ");131 defaults.email = user.email;132 if (row?.phone) defaults.phone = row.phone;133 if (row?.company) defaults.organization = row.company;134 if (row?.job_title) defaults.job_title = row.job_title;135 if (row?.website) defaults.website = row.website;136 if (row?.city) defaults.ville = row.city;137 const socials = parseSocials(row?.socials ?? null);138 if (socials.linkedin) defaults.linkedin_url = socials.linkedin;139 }140141 return (142 <main className="mx-auto max-w-4xl px-4 py-12 sm:px-6">143 <nav aria-label="Fil d'Ariane">144 <a href="/contact" className="gk-mono text-[11px] font-bold tracking-[0.1em] text-ink-3 uppercase no-underline hover:text-green">145 ← Centre de communication146 </a>147 </nav>148149 <div className="mt-6 flex items-start gap-5">150 <span className="hidden h-14 w-14 flex-none items-center justify-center rounded-xl border-[1.5px] border-ink bg-ink text-lime sm:flex">151 <CategoryIcon name={cat.icon} className="h-7 w-7" />152 </span>153 <div>154 <p className="kicker">Nous joindre · KA-{cat.prefix}</p>155 <h1 className="gk-display mt-2 text-[clamp(26px,4.5vw,40px)] leading-[1.02] font-bold tracking-[-0.03em] uppercase">156 {cat.title}157 </h1>158 </div>159 </div>160161 {cat.slug === "investisseurs" ? (162 <InvestisseursIntro />163 ) : cat.slug === "carrieres" ? (164 <CarrieresIntro />165 ) : (166 <p className="mt-6 max-w-3xl text-[14.5px] leading-relaxed text-ink-2">{cat.intro}</p>167 )}168 {cat.slug === "securite" ? <SecuriteIntro /> : null}169170 <ContactForm171 slug={cat.slug}172 fields={cat.fields}173 defaults={defaults}174 kaConnected={!!user}175 />176 </main>177 );178}179